package com.gitee.wsl.struct.grammar.parser.token

import com.gitee.wsl.struct.grammar.parser.Parser
import com.gitee.wsl.struct.grammar.parser.ParsingScope
import com.gitee.wsl.struct.grammar.parser.result.NoMatchingToken
import com.gitee.wsl.struct.grammar.parser.result.getOrElse

fun interface Token: Parser<TokenMatch> {
    val name: String? get() = null
    val ignored: Boolean get()= false

    val firstChars: String get() = ""

    fun match(input: CharSequence, fromIndex: Int): Int

    override suspend fun ParsingScope.parse(): TokenMatch {
        return tryParse(this@Token).getOrElse { fail(it) }
    }

    companion object{
        val Eof: Token = object: AbstractToken("EOF") {
            override fun match(input: CharSequence, fromIndex: Int): Int {
                return if (fromIndex >= input.length) 1 else 0
            }
        }

        fun fail( baseToken: Token) = FailToken(baseToken)

        /** Token type indicating that there was no [Token] found to be matched by a [Tokenizer]. */
        val noneMatched: Token = object : AbstractToken("no token matched") {
            override fun match(input: CharSequence, fromIndex: Int): Int = 0
            override fun toString(): String = "noneMatched!"
        }
    }
}

class FailToken(val baseToken: Token): Token by baseToken{
    override suspend fun ParsingScope.parse(): TokenMatch {
         fail(NoMatchingToken(position))
    }
}
